package common;

import cn.hutool.core.io.IoUtil;
import cn.hutool.json.JSONUtil;
import lombok.Getter;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.support.AnnotationConsumer;
import org.junit.platform.commons.util.Preconditions;

import java.lang.reflect.Parameter;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

/**
 * 自定义json文件源
 */
@Getter
public class JsonFileArgumentsProvider implements ArgumentsProvider, AnnotationConsumer<JsonFileSource> {

    private JsonFileSource annotation;

    /**
     * 这里会传标注在测试方法上的@JsonFileSource注解
     * @param jsonFileSource the input argument
     */
    @Override
    public void accept(JsonFileSource jsonFileSource) {
        this.annotation = jsonFileSource;
    }

    @Override
    public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) throws Exception {
        String displayName = extensionContext.getDisplayName();
        System.out.println(displayName);

        return Arrays.stream(annotation.resources())
                .map(resource -> parseToBean(extensionContext, resource))
                .map(Arguments::of);
    }

    private Object parseToBean(ExtensionContext context, String resource) {
        Preconditions.notBlank(resource, "Classpath resource [" + resource + "] must not be null or blank");
        Class<?> testClass = context.getRequiredTestClass();
        Parameter[] parameters = context.getRequiredTestMethod().getParameters();
        if (parameters.length > 0 && parameters[0].getType().isAssignableFrom(List.class)) {
            return JSONUtil.toList(JSONUtil.parseArray(IoUtil.read(testClass.getClassLoader().getResourceAsStream(resource), Charset.forName(annotation.encoding()))), annotation.typeClass());
        }
        return JSONUtil.toBean(IoUtil.read(testClass.getClassLoader().getResourceAsStream(resource), Charset.forName(annotation.encoding())), annotation.typeClass());
    }
}
